﻿using System;
using Heaven.Texturing;

namespace Heaven.Graphics
{
    /// <summary>
    /// Represents 2-dimentional render target
    /// </summary>
    public class RenderTarget : Texture, IDisposable
    {
        #region Events

        /// <summary>
        /// This event for internal use only. It notices that 
        /// the device have to update layer data
        /// </summary>
        public event EventHandler DataRequested;

        /// <summary>
        /// This event for internal use only. It notices that 
        /// the device have to dispose this render target
        /// </summary>
        public event EventHandler DisposeRequested;

        #endregion

        #region Fields

        /// <summary>
        /// Width of the layer
        /// </summary>
        protected int width;

        /// <summary>
        /// Height of the layer
        /// </summary>
        protected int height;

        /// <summary>
        /// Format of texels
        /// </summary>
        protected LayerFormat format;

        /// <summary>
        /// Content of this render target
        /// </summary>
        protected byte[] data = null;
        bool needUpdateData = true;

        #endregion

        #region Properties

        /// <summary>
        /// Format of the texture (the main layer 
        /// and mipmaps must have the same format)
        /// </summary>
        public LayerFormat Format
        {
            get { return format; }
        }

        /// <summary>
        /// Width of the layer
        /// </summary>
        public int Width
        {
            get { return width; }
        }

        /// <summary>
        /// Height of the layer
        /// </summary>
        public int Height
        {
            get { return height; }
        }

        /// <summary>
        /// Content of this render target
        /// </summary>
        public byte[] Data
        {
            get 
            {   
                if (needUpdateData)
                {
                    if (data == null)
                    {
                        data = new byte[width * height * format.ElementSize];
                        Changed += new EventHandler(OnRenderTargetChanged);
                    }
                    needUpdateData = false;
                    if (DataRequested != null) DataRequested(this, EventArgs.Empty);                    
                }
                return data;
            }
        }

        #endregion

        #region Initialization

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="width">Width</param>
        /// <param name="height">Height</param>
        /// <param name="format">Format</param>
        public RenderTarget(int width, int height, LayerFormat format) : base()
        {
            this.width = width;
            this.height = height;
            this.format = format;
        }

        void OnRenderTargetChanged(object sender, EventArgs e)
        {
            needUpdateData = true;
        }

        #endregion

        #region Methods

        /// <summary>
        /// Force disposing this render target immediately 
        /// </summary>
        public void Dispose()
        {
            GC.SuppressFinalize(this);
            if (DisposeRequested != null) DisposeRequested(this, EventArgs.Empty);            
        }

        #endregion
    }
}
